/*
 * gdt.h
 * 
 * Global Descriptor Table
 * 
 */

#ifndef __GDT_H__
#define __GDT_H__

#include <types.h>

/* Campos del descriptor de GDT */

#define GDT_DESC_BASE(dir) 	(((uint_64)(dir) & BITS_00_15) << 16 | ((uint_64)(dir) & BITS_16_23) << 16 | ((uint_64)(dir) & BITS_24_31) << 32)
#define GDT_DESC_LIMIT(dir) (((uint_64)(dir) & BITS_00_15) | ((uint_64)(dir) & BITS_16_19) << 32)

#define GDT_DESC_TYPE(type) (((uint_64)(type)) << (32 + 8))
#define GDT_DESC_S 			(((uint_64) 1) << (32 + 12))		// Tipo de Descriptor (0 para segmento del sistema - 1 para segmento de codigo o datos)
#define GDT_DESC_DPL(level) (((uint_64) level) << (32 + 13))	// Nivel de Privilegio del Descriptor
#define GDT_DESC_P 			(((uint_64) 1) << (32 + 15))		// Segmento Presente
#define GDT_DESC_AVL		(((uint_64) 1) << (32 + 20))		// Disponible para Uso de Software del Sistema
#define GDT_DESC_L 			(((uint_64) 1) << (32 + 21))		// Segmento de Codigo de 64 bits
#define GDT_DESC_DB 		(((uint_64) 1) << (32 + 22))		// Default Operation Size (0 para segmentos de 16 bits - 1 para segmentos de 32 bits)
#define GDT_DESC_G 			(((uint_64) 1) << (32 + 23))		// Granularidad (0 para Bytes - 1 para 4 KBytes) 

/* Atributos para tipos de descriptores de codigos o datos */

#define GDT_TYPE_DATA		0x0 	// Read-Only
#define GDT_TYPE_DATA_A		0x1		// Read-Only, Accessed
#define GDT_TYPE_DATA_W		0x2		// Read-Write
#define GDT_TYPE_DATA_AW	0x3 	// Read-Write, Accessed
#define GDT_TYPE_DATA_E		0x4		// Read-Only, Expand-Down
#define GDT_TYPE_DATA_AE	0x5 	// Read-Only, Accessed, Expand-Down
#define GDT_TYPE_DATA_WE	0x6 	// Read-Write, Expand-Down
#define GDT_TYPE_DATA_AWE	0x7 	// Read-Write, Accessed, Expand-Down

#define GDT_TYPE_CODE		0x8		// Execute-Only
#define GDT_TYPE_CODE_A    	0x9 	// Execute-Only, Accessed
#define GDT_TYPE_CODE_R   	0xA 	// Execute-Read
#define GDT_TYPE_CODE_AR	0xB		// Execute-Read, Accessed
#define GDT_TYPE_CODE_C    	0xC 	// Execute-Only, Conforming
#define GDT_TYPE_CODE_AC	0xD		// Execute-Only, Accessed, Conforming
#define GDT_TYPE_CODE_RC	0xE		// Execute-Read, Conforming
#define GDT_TYPE_CODE_ARC	0xF		// Execute-Read, Accessed, Conforming

/* Atributos para tipos de descriptores de sistema */

#define GDT_TYPE_S_16BTSSA 	0x1 	// 16-bit TSS (Available)
#define GDT_TYPE_S_LDT      0x2 	// LDT
#define GDT_TYPE_S_16BTSSB  0x3 	// 16-bit TSS (Busy)
#define GDT_TYPE_S_16BCG    0x4 	// 16-bit Call Gate
#define GDT_TYPE_S_TG       0x5 	// Task Gate
#define GDT_TYPE_S_16BIG    0x6 	// 16-bit Interrupt Gate
#define GDT_TYPE_S_16BTG    0x7 	// 16-bit Trap Gate
									// Reserved
#define GDT_TYPE_S_32BTSSA  0x9 	// 32-bit TSS (Available)
									// Reserved
#define GDT_TYPE_S_32BTSSB  0xB 	// 32-bit TSS (Busy)
#define GDT_TYPE_S_32BCG    0xC 	// 32-bit Call Gate
#define GDT_TYPE_S_32BIG    0xE 	// 32-bit Interrupt Gate
#define GDT_TYPE_S_32BTG    0xF 	// 32-bit Trap Gate


#define GDT_NULL ((uint_64) 0)

/* Indices en la GDT */

#define GDT_INDEX_NULL 		0x0
#define GDT_INDEX_KERNEL_C	0x1
#define GDT_INDEX_KERNEL_D	0x2
#define GDT_INDEX_USER_C	0x3
#define GDT_INDEX_USER_D	0x4
#define GDT_INDEX_TSS		0x5

/* Estructura del GDT Register */

typedef struct str_gdt_reg
{ 
    uint_16 gdt_length;
    uint_32 gdt_addr;
} __attribute__((__packed__)) gdt_reg; 

/* Exports */

extern uint_64 gdt_table[];

#endif /* __GDT_H__ */

